package com.gitee.wsl.security.encrypt.sample

import com.gitee.wsl.ext.map.sortByKey
import com.gitee.wsl.security.encrypt.Encrypt
import com.gitee.wsl.security.encrypt.StringToStringEncrypt
import kotlin.math.abs

/**
 * normal @link https://ctf.bugku.com/tool/railfence type w @link
 * https://en.wikipedia.org/wiki/Rail_fence_cipher https://ctf.bugku.com/tool/railfence
 */
class RailFenceW(val key: Int,val offset: Int = 0): StringToStringEncrypt {
    override fun decrypt(src: String): String {
        val cycle = 2 * (key - 1)
        val l = Array(src.length) { '0' }
        var j = 0
        for (y in 0 until key) {
            for (x in src.indices) {
                if ((y + x + offset) % cycle == 0 || (y - x - offset) % cycle == 0) {
                    l[x] = src[j++]
                }
            }
        }
        return l.joinToString("")
    }

    override fun encrypt(src: String): String {
        val cycle = 2 * (key - 1)
        return src.foldIndexed(mutableMapOf<Int, MutableList<Char>>()){ pos, acc, c ->
            acc.apply {
                val propIndex = key - 1 - abs(cycle / 2 - (pos + offset) % cycle)
                this[propIndex]?.add(c) ?: kotlin.run { this[propIndex] = mutableListOf(c) }
            }
        }.sortByKey(Int::compareTo).values.joinToString("") { it.joinToString("") }
        /*return src.asIterable()
            .foldIndexed(mutableMapOf<Int, MutableList<Char>>()) { pos, acc, c ->
                acc.apply {
                    val propIndex = key - 1 - abs(cycle / 2 - (pos + offset) % cycle)
                    this[propIndex]?.add(c) ?: kotlin.run { this[propIndex] = mutableListOf(c) }
                }
            }
            .toSortedMap()
            .values
            .joinToString("") { it.joinToString("") }*/
    }

}

fun Encrypt.Companion.railFenceW(key: Int, offset: Int = 0) = RailFenceW(key, offset)